今天要來講 Cpp Service 的部分,Service 是一種一問一答的通訊方式,請求的一方是客戶端,提供資料的叫做伺服器,在這邊幫大家複習一下 Service 跟 Topic 的差異在於:
今天要做的是去模擬一個客戶端跟伺服器互相聊天的過程。而創建的過程跟昨天類似,不熟悉的人可以去看一下昨天的,下面是待會的順序。
首先我們需要建立一個套件包
cd ~/catkin_ws/src
catkin_create_pkg service_demo roscpp rospy std_msgs
接下來要創建資料夾跟 srv檔案
cd service_demo
mkdir srv
cd srv
nano Greeeting.srv
接下來一樣去定義他的資料結構
string name
int32 age
---
string feedback
這邊先提一下,在編譯以後,他一樣會自動生成幾個 .hg 檔, 但是因為他是 service , 所以會有全部的 Greeeting.h 、 請求的 GreeetingRequest.h 和 發送回復的 GreeetingResponse.h 。它的位置在 ~/catkin_ws/devel/include/service_demo/
裡面,我們以後要用的時候就是去 include 他。
在定義好通訊方式的結構後,我們要開始寫伺服器的部分。
//引用套件
# include <ros/ros.h>
# include <service_demo/Greeting.h>
// 定義請求處理的 function,我們定義的是 bool function ,如果正確回全 true,錯誤則相反
bool handle_function(service_demo::Greeting::Request &req,
service_demo::Greeting::Response &res)
{
// 我們直接把請求給印出來
ROS_INFO("Request from %s with age %d ", req.name.c_str(), req.age);
// 處理請求,並將結果寫到 回應 裡面 ,跟客戶端說 嗨~
res.feedback = "Hi " + req.name + ". I'm server!";
// 回復正確,表示正確的完成了請求
return true;
}
int main(int argc, char **argv)
{
// 初始化參數,第三個參數位置是節點名稱
ros::init(argc, argv, "greetings_server");
// 創建一個把手,讓我們可以在後面輕鬆地來處理節點
ros::NodeHandle nh;
// 定義 service 的 伺服器 ,service 名稱為 “greetings” ,收到請求之後把值傳給handle_function 進行處理
ros::ServiceServer service = nh.advertiseService("greetings", handle_function);
// 重複查詢是否要跑
ros::spin();
return 0;
}
在定義好 伺服器,開始定義客戶端啦
//引用套件
# include "ros/ros.h"
# include "service_demo/Greeting.h"
int main(int argc, char **argv)
{
// 初始化參數,第三個參數位置是節點名稱
ros::init(argc, argv, "greetings_client");
ros::NodeHandle nh;
// 定義 伺服器的 客戶端,service 名字為 “greetings”,service 類型為 Service_demo
ros::ServiceClient client = nh.serviceClient<service_demo::Greeting>("greetings");
// 設置 srv 請求消息的內容,這裡 request 包含兩個變數,name 和 age。
srv.request.name = "HAN";
srv.request.age = 20;
if (client.call(srv))
{
// 注意我們請求的內容只包含一個變數 response,在接收後要級的把它轉成字串
ROS_INFO("Response from server: %s", srv.response.feedback.c_str());
}
else
{
ROS_ERROR("Failed to call service Service_demo");
return 1;
}
return 0;
}
我們可以去把 srv 裡面的檔案想成這樣:
struct Greeting
{
struct Request
{
string name;
int age;
}request;
struct Response
{
string feedback;
}response;
}
它裡面有兩個結構,一個是 Request 一個是 Response ,然後裡面又各自是各自的東西。
client.call 是去跟我們的伺服器去聊天,如果伺服器有回他,沒有以讀不回,就代表成功了~
修改 CMakeList.txt & package.xml 的部分跟昨天是一樣的,所以這邊就不講啦! 忘記的話可以去看一下昨天的部分來複習。
今天就到這邊了~ 明天繼續看 Ros Cpp ~